import 'dart:io';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:my_flutter_core/my_flutter_core.dart';

/// IMPORTANT!!!
/// From image_cropper v1.2.0, you have to migrate your android project to v2 embedding.
/// Otherwise you might encounter the error.
/// On Android only. On cold start - works correctly. After closing app by back pressing and then opens from recent apps:
/// MissingPluginException (MissingPluginException(No implementation found for method cropImage on channel plugins.hunghd.vn/image_cropper))
/// https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects
///
/// IMPORTANT!!!
/// Why [StatefulWidget] instead of [Provider] here?
/// We use [_avatarUrl] compare with [widget.initialAvatarUrl] in order to display a prompt to user if value is different.
/// When [ChangeNotifier] notifies all the listeners current class's constructor and builder will be called once again.
/// Only once, no more even the value might change again. The execution order is change value -> constructor -> build.
/// It causes the changed value in [_avatarUrl] lost due to the class instantiation.
/// But the [initState] is not called again. That's why use [StatefulWidget] instead of [Provider] here.
class UserAvatar extends StatefulWidget {
  const UserAvatar(
    this.userId,
    this.initialAvatarUrl,
    this.onConfirmed, {
    super.key,
  });

  final String userId;
  final String initialAvatarUrl;
  final ValueChanged<String>? onConfirmed;

  @override
  State<UserAvatar> createState() => _UserAvatarState();
}

class _UserAvatarState extends State<UserAvatar> {
  final ImagePicker _imagePicker = ImagePicker();
  final FileService _fileService = FileService();

  late String _avatarUrl = widget.initialAvatarUrl;

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: _buildAppBar(), body: _buildBody());
  }

  /// Builds app bar.
  PreferredSizeWidget _buildAppBar() {
    return AppBar(
      backgroundColor: Colors.black,
      iconTheme: const IconThemeData(
        // It changes the back button and icon button color.
        // Because theme chagnes the app bar icon color automatically and we don't want it to be black.
        // That's why we set it to white manually.
        // https://stackoverflow.com/questions/51508257/how-to-change-the-appbar-back-button-color
        color: Colors.white,
      ),
      elevation: 0.0,
      title: Text(
        '头像',
        style: Theme.of(
          context,
        ).appBarTheme.titleTextStyle?.copyWith(color: Colors.white),
      ),
      actions: <Widget>[
        IconButton(
          icon: const Icon(Icons.more_horiz),
          onPressed: () {
            showModalBottomSheet(
              context: context,
              builder: (context) {
                return getSelectionBottomSheetContent([
                  ListTile(
                    leading: const Icon(Icons.photo_camera),
                    title: const Text('用相机拍摄'),
                    onTap: () {
                      NavigatorHelper.pop(context);
                      _takePhotoToUpload();
                    },
                  ),
                  ListTile(
                    leading: const Icon(Icons.photo_album),
                    title: const Text('从相册选择'),
                    onTap: () {
                      NavigatorHelper.pop(context);
                      _selectImageToUpload();
                    },
                  ),
                ], isHoriz: false);
              },
            );
          },
        ),
      ],
    );
  }

  /// Builds main body.
  Widget _buildBody() {
    return Container(
      color: Colors.black,
      child: Center(
        child: Hero(
          tag: widget.userId,
          child: CachedNetworkImage(imageUrl: _avatarUrl, fit: BoxFit.contain),
        ),
      ),
    );
  }

  /// Selects the image from gallery.
  Future<void> _selectImageToUpload() async {
    final image = await _imagePicker.pickImage(source: ImageSource.gallery);
    _cropImageUpload(image);
  }

  /// Takes photo via camera.
  Future<void> _takePhotoToUpload() async {
    if (await requestCameraPermissions()) {
      final image = await _imagePicker.pickImage(source: ImageSource.camera);
      _cropImageUpload(image);
    }
  }

  /// Crops provided image file then uploads it.
  Future<void> _cropImageUpload(XFile? image) async {
    // Just in case that use cancels action.
    if (image != null) {
      final croppedImagePath = await _cropImage(image.path);
      _upload(croppedImagePath);
    }
  }

  /// Crops the image by the input [imagePath].
  Future<String?> _cropImage(String? imagePath) async {
    if (imagePath.isNotNullOrEmpty) {
      const title = '裁剪';

      // IMPORTANT!!!
      // From image_cropper v1.2.0, you have to migrate your android project to v2 embedding.
      // Otherwise you might encounter the error.
      // On Android only. On cold start - works correctly. After closing app by back pressing and then opens from recent apps:
      // MissingPluginException (MissingPluginException(No implementation found for method cropImage on channel plugins.hunghd.vn/image_cropper))
      // https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects
      final croppedImage = await ImageCropper().cropImage(
        sourcePath: imagePath!,
        uiSettings: [
          AndroidUiSettings(
            toolbarTitle: title,
            initAspectRatio: CropAspectRatioPreset.ratio3x2,
            lockAspectRatio: false,
          ),
          IOSUiSettings(
            title: title,
            doneButtonTitle: '完成',
            cancelButtonTitle: '取消',
            minimumAspectRatio: 1.0,
          ),
        ],
      );

      return croppedImage?.path;
    } else {
      return null;
    }
  }

  /// Uploads the input file.
  Future<void> _upload(String? imageFileFullName) async {
    if (imageFileFullName.isNullOrEmpty) {
      return;
    }

    final image = File(imageFileFullName!);

    if (await image.exists() && mounted) {
      showInProgressOverlay(context, message: '上传中');

      // Gets the updated avatar url.
      final avatarUrl = await _fileService.uploadOwnAvatarByBase64(image);

      // Triggers the UI build to display the updated avatar.
      setState(() => _avatarUrl = avatarUrl);

      // Passes the updated url to caller if needed.
      widget.onConfirmed?.call(avatarUrl);

      if (mounted) {
        // Pops progress overlap.
        NavigatorHelper.pop(context);
      }
    }
  }

  /// Checks the data before popping.
  //  Future<bool> _onWillPop() async {
  //    // If the page is popping up while being changed without saving then the confirm dialog will be displayed.
  //    if (!checkNullOrEmpty(_avatarUrl) &&
  //        _avatarUrl != widget.initialAvatarUrl) {
  //      UserInteraction(context: context).showConfirmDialog('放弃保存？',
  //          confirmCallback: () => NavigatorHelper.pop(context));
  //    } else {
  //      // Allows to close current page.
  //      return true;
  //    }
  //
  //    // It stops the original Navigator.pop action.
  //    return false;
  //  }
}
